﻿using System;
using System.Collections;
using System.Configuration.Install;
using System.Diagnostics;
using System.IO;
using System.ServiceProcess;
using WatchDog.ServiceProcess;

namespace WatchDog
{
    /// <summary>
    /// Windows服务管理类
    /// </summary>
    public class WindowsServiceManage
    {
        /// <summary>
        /// 判断服务是否存在
        /// </summary>
        /// <param name="serviceName"></param>
        /// <returns></returns>
        public static bool IsServiceExisted(string serviceName)
        {
            try
            {
                ServiceController[] services = ServiceController.GetServices();
                foreach (ServiceController sc in services)
                {
                    if (sc.ServiceName.Equals(serviceName, StringComparison.OrdinalIgnoreCase))
                    {
                        return true;
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("Error checking if service exists: " + ex.Message);
            }
            return false;
        }

        /// <summary>
        /// 安装服务
        /// </summary>
        /// <param name="serviceFilePath"></param>
        public static string InstallService(string serviceFilePath, string serviceName, string displayName, bool netframeWsMethod = false)
        {
            try
            {
                if (netframeWsMethod)
                {
                    #region 旧方法
                    var serviceProcessInstaller1 = new ServiceProcessInstaller();
                    var serviceInstaller1 = new ServiceInstaller();

                    serviceProcessInstaller1.Account = ServiceAccount.LocalSystem;
                    serviceProcessInstaller1.Password = null;
                    serviceProcessInstaller1.Username = null;

                    serviceInstaller1.DisplayName = displayName;
                    serviceInstaller1.ServiceName = serviceName;
                    serviceInstaller1.StartType = ServiceStartMode.Automatic;
                    serviceInstaller1.DelayedAutoStart = true;

                    using (var installer = new AssemblyInstaller())
                    {
                        if (System.IO.Path.GetExtension(serviceFilePath).ToLower() == ".dll")
                        {
                            var logFilePath = System.IO.Path.ChangeExtension(serviceFilePath, ".InstallLog");
                            var assemblyPath = System.IO.Path.ChangeExtension(serviceFilePath, ".exe");
                            installer.UseNewContext = false;
                            installer.Path = serviceFilePath;
                            installer.Context = new InstallContext(logFilePath, new string[0]);
                            installer.Context.Parameters["assemblyPath"] = assemblyPath;

                        }
                        else
                        {
                            installer.UseNewContext = true;
                            installer.Path = serviceFilePath;
                        }

                        IDictionary savedState = new Hashtable();
                        installer.Install(savedState);
                        installer.Commit(savedState);
                    }
                    #endregion
                }
                else
                {
                    #region 新方法
                    // 创建服务控制文件（.scf）
                    //ServiceController serviceController = new ServiceController(serviceName);
                    //string scfPath = Path.Combine(Path.GetDirectoryName(serviceFilePath), serviceController.ServiceName + ".scf");
                    //using (StreamWriter sw = new StreamWriter(scfPath))
                    //{
                    //    sw.WriteLine("[Service]");
                    //    sw.WriteLine("Name=" + serviceController.ServiceName);
                    //    sw.WriteLine("DisplayName=" + serviceController.DisplayName);
                    //    sw.WriteLine("StartMode=Automatic");
                    //    sw.WriteLine("Started=true");
                    //    sw.WriteLine("Path=" + serviceFilePath);
                    //}
                    ProcessStartInfo psi = new ProcessStartInfo
                    {
                        FileName = "sc",  // 系统服务控制程序的路径，通常在系统目录下
                        Arguments = $"create \"{serviceName}\" binPath={serviceFilePath} start=auto  DisplayName=\"{displayName}\" ",  // 创建服务命令，指定服务名称、可执行文件路径、启动模式等参数
                        UseShellExecute = false,  // 使用系统外壳程序启动命令
                        CreateNoWindow = true  // 不创建新窗口
                    };
                    Process.Start(psi).WaitForExit();  // 执行命令并等待退出
                    #endregion
                }

            }
            catch (Exception ex)
            {
                return ex.Message;
            }
            return null;
        }

        /// <summary>
        /// 卸载服务
        /// </summary>
        /// <param name="serviceFilePath"></param>
        public static string UninstallService(string serviceName, bool netframeWsMethod = false, string serviceFilePath = null)
        {
            try
            {

                if (netframeWsMethod)
                {
                    #region 旧方法
                    // 旧方法，不推荐使用，因为需要使用InstallUtil.exe，而InstallUtil.exe在.NET 6中 被移除了。
                    using (var installer = new AssemblyInstaller())
                    {
                        if (System.IO.Path.GetExtension(serviceFilePath).ToLower() == ".dll")
                        {
                            var logFilePath = System.IO.Path.ChangeExtension(serviceFilePath, ".InstallLog");
                            var assemblyPath = System.IO.Path.ChangeExtension(serviceFilePath, ".exe");
                            installer.UseNewContext = false;
                            installer.Path = serviceFilePath;
                            installer.Context = new InstallContext(logFilePath, new string[0]);
                            installer.Context.Parameters["assemblyPath"] = assemblyPath;
                        }
                        else
                        {
                            installer.UseNewContext = true;
                            installer.Path = serviceFilePath;
                        }

                        installer.Uninstall(null);
                    }
                    #endregion
                }
                else
                {
                    #region 新
                    // 卸载服务
                    using (Process p = new Process())
                    {
                        p.StartInfo.FileName = "sc";
                        p.StartInfo.Arguments = "stop " + serviceName;
                        p.StartInfo.UseShellExecute = true;
                        p.StartInfo.CreateNoWindow = false;
                        p.Start();
                        p.WaitForExit();
                    }

                    using (Process p = new Process())
                    {
                        p.StartInfo.FileName = "sc";
                        p.StartInfo.Arguments = "delete " + serviceName;
                        p.StartInfo.UseShellExecute = true;
                        p.StartInfo.CreateNoWindow = false;
                        p.Start();
                        p.WaitForExit();
                    }

                    Console.WriteLine("Service uninstalled successfully.");

                    #endregion
                }
            }
            catch (Exception ex)
            {
                return ex.Message;
            }
            return null;
        }

        /// <summary>
        /// 启动服务
        /// </summary>
        /// <param name="serviceName"></param>
        public static string ServiceStart(string serviceName)
        {
            //var timeout = TimeSpan.FromSeconds(60);
            using (var service = new ServiceController(serviceName))
            {
                try
                {
                    if (service.Status == ServiceControllerStatus.Stopped)
                    {
                        service.Start();
                        service.WaitForStatus(ServiceControllerStatus.Running);
                    }
                }
                catch (Exception ex)
                {
                    return ex.Message;
                }
            }
            return null;
        }


        /// <summary>
        /// 向服务发送命令
        /// </summary>
        /// <param name="serviceName"></param>
        /// <param name="command">一个应用程序定义的命令标志，指示要执行的自定义命令。该值必须介于 128 和 256 之间</param>
        public static string ExecuteCommand(string serviceName, WindowsServiceCustomCommands command)
        {
            using (var service = new ServiceController(serviceName))
            {
                try
                {
                    if (service.Status == ServiceControllerStatus.Running)
                    {
                        service.ExecuteCommand((int)command);
                    }
                }
                catch (Exception ex)
                {
                    return ex.Message;
                }
            }
            return null;
        }
        /// <summary>
        /// 停止服务
        /// </summary>
        /// <param name="serviceName"></param>
        public static string ServiceStop(string serviceName)
        {
            using (var service = new ServiceController(serviceName))
            {
                try
                {
                    if (service.Status == ServiceControllerStatus.Running)
                    {
                        service.Stop();
                        service.WaitForStatus(ServiceControllerStatus.Stopped);
                    }
                }
                catch (Exception ex)
                {
                    return ex.Message;
                }
            }
            return null;
        }

        /// <summary>
        /// 重启服务
        /// </summary>
        /// <param name="serviceName"></param>
        /// <returns></returns>
        public static string ServiceRestart(string serviceName)
        {
            using (var service = new ServiceController(serviceName))
            {
                try
                {
                    if (service.Status == ServiceControllerStatus.Running)
                    {
                        service.Stop();
                        service.WaitForStatus(ServiceControllerStatus.Stopped);
                    }
                    service.Start();
                    service.WaitForStatus(ServiceControllerStatus.Running);
                }
                catch (Exception ex)
                {
                    return ex.Message;
                }
            }
            return null;
        }

        /// <summary>
        /// 获取服务状态
        /// </summary>
        /// <returns></returns>
        public static ServiceControllerStatus GetServiceStatus(string serviceName)
        {

            using (var serviceController = new ServiceController(serviceName))
                return serviceController.Status;


        }
        /// <summary>
        /// 获取服务状态描述
        /// </summary>
        /// <param name="serviceName"></param>
        /// <returns></returns>
        public static string GetStatusDescription(string serviceName)
        {
            try
            {
                switch ((int)WindowsServiceManage.GetServiceStatus(serviceName))
                {
                    case 1: return "已停止"; break;//已停止
                    case 2: return "启动中"; break;//启动中
                    case 3: return "停止中"; break;//停止中
                    case 4: return "运行中"; break;//运行中
                    case 5: return "继续中"; break;//继续中
                    case 6: return "暂停中"; break;//暂停中
                    case 7: return "已暂停"; break;//已暂停
                    default: return "未安装"; break;//未知状态，可能服务不存在或未安装。
                }
            }
            catch (InvalidOperationException ex)
            {
                return "未安装";//服务不存在或未安装。
            }
        }

        private static void CorrectAssemblyPath(InstallContext context)
        {
            string possibleDll = context.Parameters["assemblyPath"];

            if (possibleDll == null)
            {
                return;
            }

            if (possibleDll.EndsWith(".dll", StringComparison.OrdinalIgnoreCase))
            {
                var exe = possibleDll.Substring(0, possibleDll.Length - 4) + ".exe";
                context.Parameters["assemblyPath"] = exe;
            }
        }

    }
}
